package com.hzit.hzb.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hzit.common.exception.Assert;
import com.hzit.common.result.ResponseEnum;
import com.hzit.hzb.core.enums.ReturnMethodEnum;
import com.hzit.hzb.core.enums.TransTypeEnum;
import com.hzit.hzb.core.hfb.FormHelper;
import com.hzit.hzb.core.hfb.HfbConst;
import com.hzit.hzb.core.hfb.RequestHelper;
import com.hzit.hzb.core.pojo.entity.TransFlow;
import com.hzit.hzb.core.pojo.entity.UserAccount;
import com.hzit.hzb.core.mapper.UserAccountMapper;
import com.hzit.hzb.core.pojo.entity.UserInfo;
import com.hzit.hzb.core.service.TransFlowService;
import com.hzit.hzb.core.service.UserAccountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzit.hzb.core.service.UserInfoService;
import com.hzit.hzb.core.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestHeader;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 用户账户 服务实现类
 * </p>
 *
 * @author hbxfwf
 * @since 2024-08-27
 */
@Service
@Slf4j
public class UserAccountServiceImpl extends ServiceImpl<UserAccountMapper, UserAccount> implements UserAccountService {
	@Autowired
	private UserInfoService userInfoService;
	@Autowired
	private TransFlowService transFlowService;

	/**
	 * 生成充值表单字符串
	 * @param chargeAmt  充值金额
	 * @param userId     用户id
	 * @return
	 */
	@Override
	public String commitCharge(BigDecimal chargeAmt, Long userId) {
		// 1. 查询出用户信息
		UserInfo userinfo = userInfoService.getById(userId);
		String bindCode = userinfo.getBindCode();
		Assert.notEmpty(bindCode, ResponseEnum.USER_NO_BIND_ERROR);
		// 2. 构造表单数据的map
		Map<String, Object> mapParam = new HashMap<>();
		// 2.1 商户维一标识
		mapParam.put("agentId",HfbConst.AGENT_ID);
		// 2.2 生成商户充值单号
		mapParam.put("agentBillNo", LendNoUtils.getLendNo());
		// 2.3 绑定的协议号
		mapParam.put("bindCode", bindCode);
		// 2.4 充值金额
		mapParam.put("chargeAmt", chargeAmt);
		// 2.5 手续费
		mapParam.put("feeAmt", new BigDecimal(0));
		// 2.6 充值的异步回调地址
		mapParam.put("notifyUrl", HfbConst.RECHARGE_NOTIFY_URL);
		// 2.7 充值的同步回调地址
		mapParam.put("returnUrl", HfbConst.RECHARGE_RETURN_URL);
		// 2.8 获取时间戳
		mapParam.put("timestamp", RequestHelper.getTimestamp());
		// 2.9 生成签名字符串
		String sign = RequestHelper.getSign(mapParam);
		// 2.10 获取签名
		mapParam.put("sign", sign);
		// 2.11 生成表单字符串
		String formStr = FormHelper.buildForm(HfbConst.RECHARGE_URL, mapParam);
		// 2.12 返回表单字符串
		return formStr;
	}

	/**
	 * 充值异步回调处理
	 * @param paramMap
	 * @return
	 */
	@Override
	public String notifyUserAccount(Map<String, Object> paramMap) {
		// 1. 修改 userAccount表
		String bindCode = paramMap.get("bindCode") + "";
		BigDecimal chargeAmt = new BigDecimal(paramMap.get("chargeAmt") + "");


		// 2. 在流水表trans_flow中查询是否有记录,有证明发送过异步回调
		String transNo = paramMap.get("agentBillNo") + "";
		TransFlow transFlow = transFlowService.getOne(new QueryWrapper<TransFlow>().eq("trans_no", transNo));
		if(transFlow != null){
			log.info("幂等性成立!");
			return "success";
		}
		// 参数1: 充值金额 参数2:bindCode 参数3:冻结金额
		baseMapper.updateUserAccount(chargeAmt,bindCode,new BigDecimal(0));
		UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("bind_code", bindCode));

		// 3. 添加流水记录
		transFlow = new TransFlow();
		transFlow.setMemo("充值");    // 备注
		transFlow.setTransAmount(chargeAmt);    // 交易金额
		transFlow.setTransNo(transNo);  // 交易流水号
		transFlow.setTransType(TransTypeEnum.RECHARGE.getTransType());  // 交易类型
		transFlow.setTransTypeName(TransTypeEnum.getTransTypeName(transFlow.getTransType()));  // 交易名字
		transFlow.setUserId(userInfo.getId());  // 用户id
		transFlow.setUserName(userInfo.getName());// 用户name
		//4. 保存流水记录
		transFlowService.save(transFlow);

		//todo... 发送充值成功消息
		// ① 携带参数：mobile + message(充值成功)
		// ② 在service-sms微服务监听到消息，再通过阿里云向用户手机发送通知消息

		return "success";
	}

	/**
	 * 根据userId获取账户余额
	 * @param userId
	 * @return
	 */
	@Override
	public BigDecimal getAccount(Long userId) {
		UserAccount userAccount = this.getOne(new QueryWrapper<UserAccount>().eq("user_id", userId));
		return userAccount.getAmount();
	}

	/**
	 * 根据还款方式确定收益
	 * @param investAmount 投资金额
	 * @param lendYearRate  年化率
	 * @param period    期数
	 * @param returnMethod  还款方式
	 * @return
	 */
	@Override
	public BigDecimal getInterestCount(BigDecimal investAmount, BigDecimal lendYearRate, Integer period, Integer returnMethod) {
		// 1. 等额本息
		if (ReturnMethodEnum.ONE.getMethod().intValue() == returnMethod.intValue()) {
			return Amount1Helper.getInterestCount(investAmount, lendYearRate, period);
		}
		// 2. 等额本金
		if (ReturnMethodEnum.TWO.getMethod().intValue() == returnMethod.intValue()) {
			return Amount2Helper.getInterestCount(investAmount, lendYearRate, period);
		}
		// 3. 每月还息一次还本
		if(ReturnMethodEnum.THREE.getMethod().intValue() == returnMethod.intValue()){
			return Amount3Helper.getInterestCount(investAmount, lendYearRate, period);
		}
		// 4. 一次还本还息
		if(ReturnMethodEnum.FOUR.getMethod().intValue() == returnMethod.intValue()){
			return Amount4Helper.getInterestCount(investAmount, lendYearRate, period);
		}
		return new BigDecimal(0);
	}

	/**
	 * 用户提现，生成表单串
	 * @param userId
	 * @param fetchAmt
	 */
	@Override
	public String commitWithdraw(Long userId, BigDecimal fetchAmt) {
		// 1. 定义传入表单的参数
		Map<String, Object> paramMap = new HashMap<>();
		String bindCode = userInfoService.getById(userId).getBindCode();
		// 2. 填写表单参数
		paramMap.put("agentId",HfbConst.AGENT_ID);                  // 给商户分配的唯一标识
		paramMap.put("agentBillNo",LendNoUtils.getWithdrawNo());    // 商户订单号
		paramMap.put("bindCode",bindCode);                          // 绑定协议号
		paramMap.put("fetchAmt",fetchAmt);                          // 提现金额
		paramMap.put("feeAmt",new BigDecimal(0));               // 手续费
		paramMap.put("returnUrl",HfbConst.WITHDRAW_RETURN_URL);     // 同步回调地址
		paramMap.put("notifyUrl",HfbConst.WITHDRAW_NOTIFY_URL);     // 异步回调地址
		paramMap.put("timestamp",RequestHelper.getTimestamp());     // 时间戳
		String sign = RequestHelper.getSign(paramMap);              // 生成签名
		paramMap.put("sign",sign);
		return FormHelper.buildForm(HfbConst.WITHDRAW_URL,paramMap);
	}

	/**
	 * 提现的异步回调
	 * @param paramMap
	 * @return
	 */
	@Override
	public String notifyWithdraw(Map<String, Object> paramMap) {
		// 1. 保证异步回调的幂等性
		String agentBillNo = paramMap.get("agentBillNo").toString();
		TransFlow transFlow = transFlowService.getOne(new QueryWrapper<TransFlow>().eq("trans_no", agentBillNo));
		if(transFlow != null){
			log.info("幂等性返回！");
			return "success";
		}
		// 2. 修改用户的账户余额
		BigDecimal fetchAmt = new BigDecimal(paramMap.get("fetchAmt").toString());
		String bindCode = paramMap.get("bindCode").toString();
		UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("bind_code", bindCode));
		baseMapper.updateUserAccount(fetchAmt.negate(),bindCode,new BigDecimal(0));
		// 3. 添加交易流水
		transFlow = new TransFlow();
		transFlow.setMemo("提现");
		transFlow.setTransAmount(fetchAmt);
		transFlow.setTransNo(agentBillNo);
		transFlow.setUserId(userInfo.getId());
		transFlow.setTransType(TransTypeEnum.WITHDRAW.getTransType());
		transFlow.setTransTypeName(TransTypeEnum.WITHDRAW.getTransTypeName());
		transFlow.setUserName(userInfo.getName());
		transFlowService.save(transFlow);

		return "success";
	}
}
